from typing import List, Dict, Optional, Tuple, Any
from tortoise.exceptions import DoesNotExist, ValidationError
from tortoise.queryset import QuerySet
from tortoise.expressions import Q
from tortoise.transactions import in_transaction
from backend.models.agent import Agent
from backend.models.user import User, Department
from backend.schemas.agent import AgentCreate, AgentUpdate, PaginationParams
import logging

logger = logging.getLogger(__name__)


class AgentService:
    """智能体服务类 - 提供智能体的增删改查操作"""
    
    @staticmethod
    async def create_agent(agent_data: AgentCreate, created_by: User) -> Agent:
        """
        创建智能体
        
        Args:
            agent_data: 智能体创建数据
            created_by: 创建者用户
            
        Returns:
            Agent: 创建的智能体实例
            
        Raises:
            ValueError: 当部门不存在或数据验证失败时
            ValidationError: 当数据格式不正确时
        """
        async with in_transaction():
            # 验证部门是否存在
            department = None
            if hasattr(agent_data, 'department_id') and agent_data.department_id:
                try:
                    department = await Department.get(dept_id=agent_data.department_id)
                except DoesNotExist:
                    raise ValueError(f"部门不存在: {agent_data.department_id}")
            
            # 验证智能体名称唯一性（同一用户下）
            existing_agent = await Agent.filter(
                name=agent_data.name, 
                created_by=created_by
            ).first()
            if existing_agent:
                raise ValueError(f"智能体名称 '{agent_data.name}' 已存在")
            
            # 构建创建数据
            create_data = {
                'name': agent_data.name,
                'description': agent_data.description,
                'avatar': getattr(agent_data, 'avatar', None),
                'category': getattr(agent_data, 'category', None),
                'agent_type': getattr(agent_data, 'agent_type', agent_data.type if hasattr(agent_data, 'type') else None),
                'status': getattr(agent_data, 'status', 'active'),
                'version': getattr(agent_data, 'version', '1.0.0'),
                'config': agent_data.config,
                'created_by': created_by,
                'department': department
            }
            
            # 移除None值
            create_data = {k: v for k, v in create_data.items() if v is not None}
            
            try:
                agent = await Agent.create(**create_data)
                logger.info(f"智能体创建成功: {agent.name} (ID: {agent.id})")
                return agent
            except Exception as e:
                logger.error(f"创建智能体失败: {str(e)}")
                raise ValidationError(f"创建智能体失败: {str(e)}")
    
    @staticmethod
    async def get_agent_by_id(agent_id: int, current_user: Optional[User] = None) -> Optional[Agent]:
        """
        根据ID获取智能体
        
        Args:
            agent_id: 智能体ID
            current_user: 当前用户（用于权限检查）
            
        Returns:
            Optional[Agent]: 智能体实例或None
        """
        try:
            agent = await Agent.get(id=agent_id).prefetch_related('created_by', 'department')
            
            # 权限检查：非超级用户只能查看自己创建的或同部门的智能体
            if current_user and not current_user.is_superuser:
                if (agent.created_by_id != current_user.id and 
                    (not current_user.department or agent.department_id != current_user.department.id)):
                    logger.warning(f"用户 {current_user.id} 尝试访问无权限的智能体 {agent_id}")
                    return None
            
            return agent
        except DoesNotExist:
            logger.warning(f"智能体不存在: {agent_id}")
            return None
    
    @staticmethod
    async def update_agent(agent_id: int, agent_data: AgentUpdate, current_user: User) -> Optional[Agent]:
        """
        更新智能体
        
        Args:
            agent_id: 智能体ID
            agent_data: 更新数据
            current_user: 当前用户
            
        Returns:
            Optional[Agent]: 更新后的智能体实例或None
            
        Raises:
            PermissionError: 当用户没有权限时
            ValueError: 当部门不存在或数据验证失败时
        """
        async with in_transaction():
            agent = await AgentService.get_agent_by_id(agent_id, current_user)
            if not agent:
                return None
            
            # 检查权限：只有创建者或管理员可以修改
            if agent.created_by_id != current_user.id and not current_user.is_superuser:
                raise PermissionError("您没有权限修改此智能体")
            
            # 验证智能体名称唯一性（如果名称有变化）
            if hasattr(agent_data, 'name') and agent_data.name and agent_data.name != agent.name:
                existing_agent = await Agent.filter(
                    name=agent_data.name, 
                    created_by=current_user
                ).exclude(id=agent_id).first()
                if existing_agent:
                    raise ValueError(f"智能体名称 '{agent_data.name}' 已存在")
            
            # 验证部门是否存在
            if hasattr(agent_data, 'department_id') and agent_data.department_id is not None:
                if agent_data.department_id:
                    try:
                        department = await Department.get(dept_id=agent_data.department_id)
                        agent.department = department
                    except DoesNotExist:
                        raise ValueError(f"部门不存在: {agent_data.department_id}")
                else:
                    agent.department = None
            
            # 更新字段
            update_data = agent_data.dict(exclude_unset=True, exclude={'department_id'})
            for field, value in update_data.items():
                if hasattr(agent, field):
                    setattr(agent, field, value)
            
            try:
                await agent.save()
                logger.info(f"智能体更新成功: {agent.name} (ID: {agent.id})")
                return agent
            except Exception as e:
                logger.error(f"更新智能体失败: {str(e)}")
                raise ValidationError(f"更新智能体失败: {str(e)}")
    
    @staticmethod
    async def delete_agent(agent_id: int, current_user: User) -> bool:
        """
        删除智能体（软删除）
        
        Args:
            agent_id: 智能体ID
            current_user: 当前用户
            
        Returns:
            bool: 删除是否成功
            
        Raises:
            PermissionError: 当用户没有权限时
        """
        async with in_transaction():
            agent = await AgentService.get_agent_by_id(agent_id, current_user)
            if not agent:
                return False
            
            # 检查权限：只有创建者或管理员可以删除
            if agent.created_by_id != current_user.id and not current_user.is_superuser:
                raise PermissionError("您没有权限删除此智能体")
            
            try:
                # 软删除：将状态设置为deleted
                agent.status = 'deleted'
                await agent.save()
                logger.info(f"智能体删除成功: {agent.name} (ID: {agent.id})")
                return True
            except Exception as e:
                logger.error(f"删除智能体失败: {str(e)}")
                return False
    
    @staticmethod
    async def hard_delete_agent(agent_id: int, current_user: User) -> bool:
        """
        硬删除智能体（物理删除）
        
        Args:
            agent_id: 智能体ID
            current_user: 当前用户
            
        Returns:
            bool: 删除是否成功
            
        Raises:
            PermissionError: 当用户没有权限时
        """
        async with in_transaction():
            agent = await AgentService.get_agent_by_id(agent_id, current_user)
            if not agent:
                return False
            
            # 检查权限：只有超级用户可以硬删除
            if not current_user.is_superuser:
                raise PermissionError("您没有权限永久删除此智能体")
            
            try:
                await agent.delete()
                logger.info(f"智能体永久删除成功: {agent.name} (ID: {agent.id})")
                return True
            except Exception as e:
                logger.error(f"永久删除智能体失败: {str(e)}")
                return False
    
    @staticmethod
    async def get_agents_list(params: PaginationParams, current_user: User) -> Tuple[List[Dict], int]:
        """
        获取智能体列表
        
        Args:
            params: 分页和筛选参数
            current_user: 当前用户
            
        Returns:
            Tuple[List[Dict], int]: (智能体列表, 总数)
        """
        try:
            # 构建查询
            query = Agent.all().prefetch_related('created_by', 'department')
            
            # 权限过滤：非超级用户只能看到自己创建的或同部门的智能体
            if not current_user.is_superuser:
                if current_user.department:
                    query = query.filter(
                        Q(created_by=current_user) | Q(department=current_user.department)
                    )
                else:
                    query = query.filter(created_by=current_user)
            
            # 默认过滤掉已删除的智能体（除非明确查询deleted状态）
            if not hasattr(params, 'status') or params.status != 'deleted':
                query = query.exclude(status='deleted')
            
            # 搜索过滤
            if hasattr(params, 'search') and params.search:
                search_term = params.search.strip()
                query = query.filter(
                    Q(name__icontains=search_term) | 
                    Q(description__icontains=search_term) |
                    Q(category__icontains=search_term)
                )
            
            # 智能体类型过滤
            if hasattr(params, 'agent_type') and params.agent_type:
                query = query.filter(agent_type=params.agent_type)
            elif hasattr(params, 'type') and params.type:  # 兼容旧字段
                query = query.filter(agent_type=params.type)
            
            # 分类过滤
            if hasattr(params, 'category') and params.category:
                query = query.filter(category=params.category)
            
            # 状态过滤
            if hasattr(params, 'status') and params.status:
                query = query.filter(status=params.status)
            
            # 部门过滤
            if hasattr(params, 'department_id') and params.department_id:
                query = query.filter(department__dept_id=params.department_id)
            
            # 获取总数
            total = await query.count()
            
            # 分页和排序
            offset = (params.page - 1) * params.limit
            agents = await query.offset(offset).limit(params.limit).order_by('-created_at')
            
            # 转换为字典格式
            result = []
            for agent in agents:
                agent_dict = AgentService._agent_to_dict(agent)
                result.append(agent_dict)
            
            logger.info(f"获取智能体列表成功: 用户 {current_user.id}, 返回 {len(result)}/{total} 条记录")
            return result, total
            
        except Exception as e:
            logger.error(f"获取智能体列表失败: {str(e)}")
            return [], 0
    
    @staticmethod
    def _agent_to_dict(agent: Agent) -> Dict[str, Any]:
        """
        将智能体模型转换为字典格式
        
        Args:
            agent: 智能体实例
            
        Returns:
            Dict[str, Any]: 智能体字典数据
        """
        return {
            'id': agent.id,
            'name': agent.name,
            'description': agent.description,
            'avatar': agent.avatar,
            'category': agent.category,
            'agent_type': agent.agent_type,
            'status': agent.status,
            'version': agent.version,
            'config': agent.config,
            'created_by_id': agent.created_by_id,
            'created_by_name': agent.created_by.name if agent.created_by else None,
            'department_id': agent.department.dept_id if agent.department else None,
            'department_name': getattr(agent.department, 'name', getattr(agent.department, 'dept_name', None)) if agent.department else None,
            'created_at': agent.created_at.isoformat() if agent.created_at else None,
            'updated_at': agent.updated_at.isoformat() if agent.updated_at else None,
        }
    
    @staticmethod
    async def get_agent_types() -> List[str]:
        """
        获取智能体类型列表
        
        Returns:
            List[str]: 智能体类型列表
        """
        # 可以从数据库动态获取或从配置文件读取
        return ["内嵌型", "外链型"]
    
    @staticmethod
    async def get_agent_categories() -> List[str]:
        """
        获取智能体分类列表
        
        Returns:
            List[str]: 智能体分类列表
        """
        # 可以从数据库动态获取已有的分类
        try:
            categories = await Agent.all().distinct().values_list('category', flat=True)
            # 过滤掉空值并添加默认分类
            result = [cat for cat in categories if cat]
            default_categories = ["客服助手", "技术支持", "营销推广", "内容创作", "数据处理", "教育培训"]
            for cat in default_categories:
                if cat not in result:
                    result.append(cat)
            return result
        except Exception as e:
            logger.error(f"获取智能体分类失败: {str(e)}")
            return ["客服助手", "技术支持", "营销推广", "内容创作", "数据处理", "教育培训"]
    
    @staticmethod
    async def get_agent_statuses() -> List[str]:
        """
        获取智能体状态列表
        
        Returns:
            List[str]: 智能体状态列表
        """
        return ["active", "inactive", "deleted"]
    
    @staticmethod
    async def get_user_agents_count(user_id: int) -> int:
        """
        获取用户创建的智能体数量
        
        Args:
            user_id: 用户ID
            
        Returns:
            int: 智能体数量
        """
        try:
            return await Agent.filter(created_by_id=user_id).exclude(status='deleted').count()
        except Exception as e:
            logger.error(f"获取用户智能体数量失败: {str(e)}")
            return 0
    
    @staticmethod
    async def search_agents(keyword: str, current_user: User, limit: int = 10) -> List[Agent]:
        """
        搜索智能体
        
        Args:
            keyword: 搜索关键词
            current_user: 当前用户
            limit: 返回数量限制
            
        Returns:
            List[Agent]: 搜索结果列表
        """
        try:
            query = Agent.all().prefetch_related('created_by', 'department')
            
            # 权限过滤
            if not current_user.is_superuser:
                if current_user.department:
                    query = query.filter(
                        Q(created_by=current_user) | Q(department=current_user.department)
                    )
                else:
                    query = query.filter(created_by=current_user)
            
            # 搜索过滤
            query = query.filter(
                Q(name__icontains=keyword) | 
                Q(description__icontains=keyword) |
                Q(category__icontains=keyword)
            ).exclude(status='deleted')
            
            agents = await query.limit(limit).order_by('-created_at')
            
            return list(agents)
            
        except Exception as e:
            logger.error(f"搜索智能体失败: {str(e)}")
            return []
    
    @staticmethod
    async def copy_agent(agent_id: int, current_user: User, copy_data=None) -> Optional[Agent]:
        """
        复制智能体
        
        Args:
            agent_id: 源智能体ID
            current_user: 当前用户
            copy_data: 复制时的自定义数据
            
        Returns:
            Optional[Agent]: 新创建的智能体实例或None
        """
        try:
            # 获取源智能体
            source_agent = await AgentService.get_agent_by_id(agent_id, current_user)
            if not source_agent:
                return None
            
            # 构建新智能体数据
            new_name = f"{source_agent.name} - 副本"
            if copy_data and hasattr(copy_data, 'name') and copy_data.name:
                new_name = copy_data.name
            
            # 检查名称唯一性
            counter = 1
            original_name = new_name
            while await Agent.filter(name=new_name, created_by=current_user).exists():
                new_name = f"{original_name} ({counter})"
                counter += 1
            
            create_data = {
                'name': new_name,
                'description': copy_data.description if copy_data and hasattr(copy_data, 'description') and copy_data.description else source_agent.description,
                'avatar': source_agent.avatar,
                'category': copy_data.category if copy_data and hasattr(copy_data, 'category') and copy_data.category else source_agent.category,
                'agent_type': source_agent.agent_type,
                'status': 'inactive',  # 复制的智能体默认为非活跃状态
                'version': '1.0.0',  # 重置版本号
                'config': source_agent.config,
                'created_by': current_user,
                'department': current_user.department if copy_data and hasattr(copy_data, 'department_id') and copy_data.department_id else source_agent.department
            }
            
            new_agent = await Agent.create(**create_data)
            logger.info(f"智能体复制成功: 源ID={agent_id}, 新ID={new_agent.id}")
            return new_agent
            
        except Exception as e:
            logger.error(f"复制智能体失败: {str(e)}")
            return None
    
    @staticmethod
    async def export_agent_config(agent_id: int, current_user: User) -> Optional[Dict[str, Any]]:
        """
        导出智能体配置
        
        Args:
            agent_id: 智能体ID
            current_user: 当前用户
            
        Returns:
            Optional[Dict[str, Any]]: 导出的配置数据或None
        """
        try:
            agent = await AgentService.get_agent_by_id(agent_id, current_user)
            if not agent:
                return None
            
            from datetime import datetime
            
            export_config = {
                'id': agent.id,
                'name': agent.name,
                'description': agent.description,
                'avatar': agent.avatar,
                'category': agent.category,
                'agent_type': agent.agent_type,
                'config': agent.config,
                'version': agent.version,
                'export_time': datetime.now().isoformat(),
                'exported_by': current_user.name
            }
            
            logger.info(f"智能体配置导出成功: ID={agent_id}")
            return export_config
            
        except Exception as e:
            logger.error(f"导出智能体配置失败: {str(e)}")
            return None
    
    @staticmethod
    async def import_agent_config(config: Dict[str, Any], current_user: User) -> Optional[Agent]:
        """
        导入智能体配置
        
        Args:
            config: 导入的配置数据
            current_user: 当前用户
            
        Returns:
            Optional[Agent]: 创建的智能体实例或None
        """
        try:
            # 验证必要字段
            required_fields = ['name', 'agent_type']
            for field in required_fields:
                if field not in config:
                    raise ValueError(f"缺少必要字段: {field}")
            
            # 检查名称唯一性
            name = config['name']
            counter = 1
            original_name = name
            while await Agent.filter(name=name, created_by=current_user).exists():
                name = f"{original_name} - 导入 ({counter})"
                counter += 1
            
            create_data = {
                'name': name,
                'description': config.get('description'),
                'avatar': config.get('avatar'),
                'category': config.get('category'),
                'agent_type': config['agent_type'],
                'status': 'inactive',  # 导入的智能体默认为非活跃状态
                'version': config.get('version', '1.0.0'),
                'config': config.get('config'),
                'created_by': current_user,
                'department': current_user.department if config.get('department_id') else None
            }
            
            agent = await Agent.create(**create_data)
            logger.info(f"智能体配置导入成功: ID={agent.id}, 名称={agent.name}")
            return agent
            
        except Exception as e:
            logger.error(f"导入智能体配置失败: {str(e)}")
            raise ValueError(f"导入智能体配置失败: {str(e)}")
    
    @staticmethod
    async def get_user_agents_count(user_id: int, current_user: User) -> int:
        """
        获取用户创建的智能体数量
        
        Args:
            user_id: 目标用户ID
            current_user: 当前用户
            
        Returns:
            int: 智能体数量
            
        Raises:
            PermissionError: 当用户没有权限时
        """
        try:
            # 权限检查：只能查看自己的或管理员可以查看所有
            if user_id != current_user.id and not current_user.is_superuser:
                raise PermissionError("您没有权限查看其他用户的智能体数量")
            
            return await Agent.filter(created_by_id=user_id).exclude(status='deleted').count()
        except PermissionError:
            raise
        except Exception as e:
            logger.error(f"获取用户智能体数量失败: {str(e)}")
            return 0
